﻿HmJS.$Import('log');
HmJS.$Import('core.core');
HmJS.$Import('lang.array');

HmJS.register('demo.module.types.arraymoo', function ($) {
	var that = {};

	// 迭代数组(包括非常规数组,如由内建的getElementsByTagName方法返回的集合对象, arguments对象, 或Ojbect对象) 
	// 
	// Syntax: Array.each(iterable, fn[, bind]);
	// 
	// Arguments: 
	//	iterable - (array) 被迭代的对象 
	//	fn - (function) 迭代过程中对每个迭代元素进行处理的函数 
	//		语法：fn(item, index, object)
	//		Arguments: 
	//			item - (mixed) 当前迭代项 
	//			index - (number) 当前迭代项的索引. 如果迭代对象是一个Oject对象, 则是对象的属性名 
	//			object - (mixed) 迭代对象
	//	bind - (object, 可选) 迭代函数中'this'所引用的对象. 详见 Function:bind. 
	// 
	// Returns: N/A
	that.each = function () {
		log.info('Array.each()---->');

		Array.each(['Sun', 'Mon'], function (day, index) {
			log.info('name:' + day + ', index: ' + index);
		}); // 显示 'name: Sun, index: 0', 'name: Mon, index: 1', 等等.

		//		['aaa', 'bbb'].each(function (item, index) {
		//			log.info('name:' + item + ', index: ' + index);
		//		});

	}

	// 返回传入数组的一个克隆数组
	// 
	// Syntax: var clone = Array.clone(myArray);
	// 
	// Arguments: 
	//	myArray - (array) 要克隆的数组
	// 
	// Returns: 
	//	(array) 传入数组的一个克隆数组
	that.clone = function () {
		log.info('Array.clone()---->');
		var myArray = ['red', 'blue', 'green'];
		var otherArray = Array.clone(myArray);
		myArray[0] = 'yellow';
		log.info(myArray.toString());
		log.info(otherArray.toString());
	}

	// 如果数组中的每一项都通过给定函数的测试, 则返回 true . 这个方法只提供给没有原生 Array:every 方法支持的浏览器
	// Returns: 
	//	(boolean) 如果数组中的每一项都通过给定函数的测试, 则返回 true ; 否则, 返回 false . 
	that.every = function () {
		log.info('Array.every()---->');
		var areAllBigEnough = [10, 4, 25, 100].every(function (item, index) {
			return item > 20;
		});
		log.info(areAllBigEnough);
	}

	// 如果数组中至少有一个项通过了给出的函数的测试, 则返回 true . 这个方法只提供给没有原生 Array:some 方法支持的浏览器
	// Returns: 
	//	(boolean) 如果数组中至少有一个项通过了给出的函数的测试, 则返回 true ; 否则返回 false 
	that.some = function () {
		log.info('Array.some()---->');
		var isAnyBigEnough = [10, 4, 25, 100].some(function (item, index) {
			return item > 20;
		});
		log.info(isAnyBigEnough);
	}

	// 将所有在给定过滤函数中过滤通过的数组项创建一个新数组. 这个方法只提供给没有原生 Array:filter 方法支持的浏览器. 
	that.filter = function () {
		log.info('Array.filter()---->');
		var resultary = [10, 56, 3, 24].filter(function (item, index) {
			return item > 20;
		});
		log.info(resultary.toString());
	}

	// 返回数组中和给出参数值相等的项的索引号; 如果未找到相等的项, 则返回 -1 . 这个方法只提供给没有原生 Array:indexOf 方法支持的浏览器. 
	// Returns: 
	//	(number) 数组中和给出参数值相等的项的索引号; 如果未找到相等的项, 则返回 -1 
	that.indexOf = function () {
		log.info('Array.indexOf()---->');
		var colors = ['red', 'blue', 'green'];
		log.info(colors.indexOf('blue'));
	}

	// 返回一个由经过给定函数处理返回的值所创建的新数组. 这个方法只提供给没有原生 Array:map 方法支持的浏览器
	that.map = function () {
		log.info('Array.map()---->');
		var r = [2, 4, 6].map(function (item, index, ary) {
			return item * index + ary.length;
		});
		log.info(r.toString());
	}

	// 返回一个由原数组中计算值为true(即不是以下情况的值: null, undefined)的项，清理数组中所有值为null或者为未定义的元素
	that.clean = function () {
		log.info('Array.clean()---->');
		var myArray = [null, 1, 0, true, false, null, 'foo', undefined, ''];
		var ary = myArray.clean() // 返回 [1, 0, true, false, 'foo', '']
		log.info(ary.toString());
	}

	// 遍历数组的各个成员, 执行其上定义的一个方法, 返回结果组成的数组
	// 提示：
	//	使用的方法应该是每个成员都拥有的. 如果某个成员的该方法不存在, 将会抛出异常.
	that.invoke = function () {
		log.info('Array.invoke()---->');
		var foo = [4, 8, 15, 16, 23, 42];
		var bar = foo.invoke('limit', 10, 30);  //bar is now [10, 10, 15, 16, 23, 30]
		log.info(bar.toLocaleString());
	}

	// 创建一个键值对对象, 该对象中的键由作为参数传入的一个数组决定, 值由主调数组决定
	// 新对象的键值对个数由两数组的长度的最小值确定
	that.associate = function () {
		log.info('Array.associate()---->');
		var animals = ['Cow', 'Pig', 'Dog', 'Cat'];
		var sounds = ['Moo', 'Oink', 'Woof', 'Miao'];
		var objtmp = sounds.associate(animals); // 返回 {'Cow': 'Moo', 'Pig': 'Oink', 'Dog': 'Woof', 'Cat': 'Miao'}
		log.info(objtmp.Cow);
	}

	// 根据给出的 “键/测试函数”对 来创建一个新的键值对对象
	// 这个方法将这个数组与一个对象做连接，这个对象中的每个值都是一个过滤函数, 创建一个新对象result，
	// 将传入的object键作为键，而原数组满足object值代表的过滤函数的第一个数组元素作为result的值，
	// 并返回result，看似强大,其实这个方法基本不会去用他..
	// 备注说明: 当前键的取值搜索范围是前一个键的测试挑选剩余后的数组项(而不是整个数组项)
	that.link = function () {
		log.info('Array.link()---->');
		var el = document.createElement('div');
		var arr2 = [100, 'Hello', { foo: 'bar' }, el, false];
		arr2.link({
			//			myNumber: Type.isNumber,
			//			myElement: Type.isElement,
			//			myObject: Type.isObject,
			//			myString: Type.isString,
			myBoolean: function (obj) { return obj != null; }
		});
		// 返回 {myNumber: 100, myElement: el, myObject: {foo: 'bar'}, myString: 'Hello', myBoolean: false}
	}

	// 测试指定项是否在数组中存在
	// Returns: 
	//	(boolean) 如果数组包含给出的项, 则返回 true ; 否则返回 false
	that.contains = function () {
		log.info('Array.contains()---->');
		log.info(['a', 'b', 'c'].contains('a')); // 返回 true
		log.info(['a', 'b', 'c'].contains('d')); // 返回 false
	}

	// 将传入的数组追加到当前数组的末尾
	// 这里需要注意的是[1,2,3].push([4,5])与[1,2,3].push.apply(this,[4,5])的结果
	// 是不同的, 这里使用到apply相当于实现了concat的效果
	that.append = function () {
		log.info('Array.append()---->');
		var myOtherArray = ['green', 'yellow'];
		log.info(['red', 'blue'].append(myOtherArray).toString()); // 返回 ['red', 'blue', 'green', 'yellow'];
		var ary = [0, 1, 2].append([3, [4, 5]]); // [0, 1, 2, 3, [4,5]]
		log.info("ary.length->" + ary.length + '-items->' + ary.toString());
	}

	// 向数组中添加一项, 如果该项在数组中已经存在, 则不再添加. (大小写与类型敏感)
	that.include = function () {
		log.info('Array.include()---->');
		var colors = ['red', 'blue', 'green'];
		colors.include('black');
		log.info(colors.toString());
	}

	// 将主调数组和另一个数组进行组合(重复的项将不会加入, 大小写和类型敏感)
	that.combine = function () {
		log.info('Array.combine()---->');
		var animals = ['Cow', 'Pig', 'Dog'];
		animals.combine(['Cat', 'Dog']); //animals = ['Cow', 'Pig', 'Dog', 'Cat'];
		log.info(animals.toString());
	}

	// 返回数组最后一个元素
	that.getLast = function () {
		log.info('Array.getLast()---->');
		log.info(['red', 'blue', 'green'].getLast());
	}

	// 返回从数组中随机抽取的一项
	that.getRandom = function () {
		log.info('Array.getRandom()---->');
		log.info(['red', 'blue', 'green'].getRandom());
	}

	// 清理数组某个指定元素,如果出现多个也一并清除
	that.erase = function () {
		log.info('Array.erase()---->');
		var ary = ['Cow', 'Pig', 'Dog', 'Cat', 'Dog'].erase('Dog') // 返回 ['Cow', 'Pig', 'Cat']
		log.info(ary.toString());
	}

	that.empty = function () {
		log.info('Array.empty()---->');
		var ary = ['Cow', 'Pig', 'Dog', 'Cat', 'Dog'];
		ary.empty();
		log.info(ary.length);
	}

	// 将多维数组扁平化(即变为一维数组)
	that.flatten = function () {
		log.info('Array.flatten()---->');
		var myArray = [1, 2, 3, [4, 5, [6, 7]], [[[8]]]];
		log.info("ary.length->" + myArray.length + '-items->' + myArray.toString());
		var newArray = myArray.flatten(); //newArray 变成 [1,2,3,4,5,6,7,8]
		log.info("ary.length->" + newArray.length + '-items->' + newArray.toString());
	}

	// 返回传入数组中第一个非未定义的项; 如果全部未定义, 则返回 null
	// 选取第一个结果不为null或undefined的元素. unshift的条件版...
	that.pick = function () {
		log.info('Array.pick()---->');
		function say(infoMessage, errorMessage) {
			log.info([errorMessage, infoMessage, 'There was no message supplied.'].pick());
		}
		say(); // 显示 'There was no message supplied.'
		say('This is an info message.'); // 显示 'This is an info message.'
		say('This message will be ignored.', 'This is the error message.'); // 显示 'This is the error message.'
	}

	// 注意：使用这个函数时必须加载core.string
	// 将十六进制的颜色代码转换成RGB格式的代码. 输入的RGB代码需要类似如下的16进制格式: ['FF', 'FF', 'FF']
	// 将一个三元素数组的值(必须为string)转化为三色值推入rgb语句，如果传入参数array计算值为true则返回处理后的数组
	// Returns: 
	//	(string) RGB格式的颜色代码字符串 
	//	(array) 如果设置了输出格式为数组, 则返回数组格式的RGB颜色代码
	that.hexToRgb = function () {
		log.info('Array.hexToRgb()---->');
		log.info(['11', '22', '33'].hexToRgb()); // 返回 'rgb(17, 34, 51)'
		var ary = ['11', '22', '33'].hexToRgb(true); // 返回 [17, 34, 51]
		log.info(ary.toString());
	}

	// 将RGB格式的颜色代码转换成十六进制的代码. 输入的RGB代码需要类似如下的其中一种格式: [255,255,255] 或 [255,255,255,1]
	// 将一个数字型数组(10进制)转换为'#ffffff'的hex颜色值的形式，如果传入参数array计算值为true则返回处理后的数组
	// Returns: 
	//	(string) 字符串格式的十六进制颜色代码, 或者若主调数组是一个代表 rgba 的颜色代码(即除了R,G,B外,还有一个Alpha值), 且第四个值是 0 , 则返回 'transparent' (透明) 
	//	(array) 如果设置了输出格式为数组, 则返回数组格式的十六进制颜色代码
	that.rgbToHex = function () {
		log.info('Array.rgbToHex()---->');
		var r1 = [17, 34, 51].rgbToHex(); // 返回 '#112233'
		var r2 = [17, 34, 51].rgbToHex(true); // 返回 ['11', '22', '33']
		var r3 = [17, 34, 51, 0].rgbToHex(); // 返回 'transparent'
		log.info(r1);
		log.info(r2);
		log.info(r3);
	}

	// Calls Math.min on the array and returns its lowest value.
	that.min = function () {
		log.info('Array.min()---->');

		var ary = [12, 2, 5, 3, 78];
		log.info(ary + '-min->' + ary.min());
	}

	// Calls Math.max on the array and returns its highest value.
	that.max = function () {
		log.info('Array.max()---->');
		var ary = [12, 2, 5, 3, 78];
		log.info(ary + '-max->' + ary.max());
	}

	// Calculates the average value of the array.
	that.average = function () {
		log.info('Array.average()---->');
		var ary = [12, 2, 5, 3, 78];
		log.info(ary + '-average->' + ary.average());
	}

	// Sums up all values in an array.
	that.sum = function () {
		log.info('Array.sum()---->');
		var ary = [12, 2, 5, 3, 78];
		log.info(ary + '-sum->' + ary.sum());
	}

	// Returns a new array without duplicate values
	that.unique = function () {
		log.info('Array.unique()---->');
		var ary = ['a', 'b', 'a', 'a', 1, 1, 1, 1, 1, 'b'];
		var ary2 = ary.unique();
		log.info(ary2.toString());
	}

	// Randomizes the array (altering it).
	that.shuffle = function () {
		log.info('Array.shuffle()---->');
		var ary = [1, 2, 3, 4, 5, 6, 7, 8];
		ary.shuffle();
		log.info(ary.toString());
	}

	// Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.
	// 
	// Syntax: result = myArray.reduce(fn[, value]);
	// 
	// Arguments: 
	//	fn - (function) Function to execute on each value in the array.
	//	value - (mixed) Value to use as the first argument to the first call of the fn
	// 
	//	Signature: fn(previousValue, currentValue, index, array)
	// 
	// Returns: 
	//	(mixed) Returns the reduced single value of the array
	that.reduce = function () {
		log.info('Array.reduce()---->');
		var result1 = [0, 1, 2, 3, 4].reduce(function (a, b) {
			return a + b;
		}); // returns 10
		var result2 = [0, 1, 2, 3, 4].reduce(function (a, b) {
			return a + b;
		}, 20); // returns 30
		log.info('result1->' + result1 + '-result2->' + result2);
	}

	// Apply a function simultaneously against two values of the array (from right-to-left) as to reduce it to a single value.
	// 
	// Syntax: result = myArray.reduceRight(fn[, value]);
	// 
	// Arguments: 
	//	fn - (function) Function to execute on each value in the array.
	//	value - (mixed) Value to use as the first argument to the first call of the fn
	// 
	//	Signature: fn(previousValue, currentValue, index, array)
	// 
	// Returns: 
	//	(mixed) Returns the reduced single value of the array.
	that.reduceRight = function () {
		log.info('Array.reduceRight()---->');
		var flattened = [[0, 1], [2, 3], [4, 5]].reduceRight(function (a, b) {
			return a.concat(b);
		}, []); // flattened is [4, 5, 2, 3, 0, 1]
		log.info(flattened.toString());
	}

	/**
	* Creates an intersection of the current array and the given one.
	* Returns as new array.
	* @param Array other	the array to use
	* @return Array
	*/
	that.intersect = function () {
		log.info('Array.intersect()---->');
		var ary1 = ['red', 'green', 'blue'];
		var ary2 = ['black', 'green'];
		var r = ary1.intersect(ary2); // return 'green'
		log.info(r.toString());
	}

	/**
	* Returns the symmetric difference between this array and the given one.
	* Means the items both arrays include are removed from both and then both are combined.
	* @param Array other	the array to use
	* @return Array
	*/
	that.differentiate = function () {
		log.info('Array.differentiate()---->');
		var ary1 = ['red', 'green', 'blue'];
		var ary2 = ['black', 'green'];
		var r = ary1.differentiate(ary2); // return 'red','blue','black'
		log.info(r.toString());
	}

	that.getRange = function () {
		log.info('Array.getRange()---->');
		var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
		var r = nums.getRange(1, 4);
		log.info(r.toString());
		var colors = ['red', 'green', 'blue'];
		var r1 = colors.getRange(1, 4);
		log.info(r1.toString());
	}

	/**
	* 把数组反序得到新数组
	* Returns the array as array in reverse order.
	* @return Array
	*/
	that.reverse4hm = function () {
		log.info('Array.reverse4hm()---->');
		var ary1 = ['red', 'green', 'blue'];
		var r = ary1.reverse4hm(); // return 'blue','green','red'
		log.info(r.toString());
	}

	return that;
});